import BaseInput from "@/components/base/Input"
import { Props, Reg } from "@/components/form_item/formItemConfig"
import styled from "@emotion/styled"
import { HTMLAttributes, useEffect, useState } from "react"
import {
    Controller,
    ControllerFieldState,
    ControllerRenderProps,
    FieldValues,
    useFormContext,
    UseFormStateReturn,
} from "react-hook-form"
import Svg from "../base/Svg"

type BaseFormItemProps = Props & { inputType: string } & {
    maxLength?: number
    /**
     *  render For example：
     *
     * <BaseFormItem
     *     fieldName="api_req_key_2"
     *     inputType='text'
     *     label="基础BaseFormItem 类型demo3"
     *     render = {({
     *         field: { onChange, onBlur, value, name, disabled},
     *         formState,
     *         fieldState,
     *         props:{ inputType}
     *     })=>{
     *         return <BaseInputs id={"inputId-" + name} type={inputType} onChange={onChange} />
     *    }}
     * />
     * */
    render?: ({
        field,
        fieldState,
        formState,
        props,
    }: {
        field: ControllerRenderProps<FieldValues, string>
        fieldState: ControllerFieldState
        formState: UseFormStateReturn<FieldValues>
        props: HTMLAttributes<HTMLInputElement> & Omit<BaseFormItemProps, "render">
    }) => React.ReactElement
}

// 支持现有组件的同时。添加自定义其他组件的功能
const BaseFormItem = (props: BaseFormItemProps) => {
    const {
        ref,
        label,
        fieldName,
        onClick,
        pattern,
        required,
        initValue,
        showClear,
        placeholder,
        isDisabled,
        inputType = "text",
        showPlaceholder = true,
        render,
        className = "",
        maxLength = 30,
        style,
    } = props
    const methods = useFormContext()
    const {
        control,
        register,
        resetField,
        clearErrors,
        watch,
        formState,
        getFieldState,
        setError,
    } = methods
    const [rule, setRule] = useState<{
        len: boolean
        ruleReg: boolean
    }>({
        len: false,
        ruleReg: false,
    })
    const Clear = () => {
        resetField(fieldName)
        clearErrors(fieldName)
    }
    const values = watch(fieldName) ?? initValue
    const errorsName = formState.errors[fieldName]
    const FieldState = getFieldState(fieldName, formState)
    useEffect(() => {
        let _rule = rule
        const TextReg = pattern ? pattern?.reg : Reg.textReg
        if (values && TextReg.test(values)) {
            _rule = {
                ..._rule,
                ...{ ruleReg: true },
            }
        } else {
            _rule = {
                ..._rule,
                ...{ ruleReg: false },
            }
            setError(fieldName, {
                message: pattern?.errorRegMsg || "Text Reg Error",
                type: "pattern",
            })
        }

        if (values && values?.length < 31) {
            _rule = {
                ..._rule,
                ...{ len: true },
            }
        } else if (values && values?.length > 30) {
            _rule = {
                ..._rule,
                ...{ len: false },
            }
            setError(fieldName, {
                message: "Text maxLength is 30",
                type: "maxLength",
            })
        }
        setRule(_rule)
        if (_rule.len && _rule.ruleReg) {
            clearErrors(fieldName)
        }
    }, [values])

    const optionsReg = {
        required: {
            message: `${fieldName} is required`,
            value: required ?? true,
        },
        value: initValue,
        disabled: isDisabled ?? false,
        maxLength: {
            value: maxLength,
            message: `Text maxLength is ${maxLength}`,
        },
        ...(pattern
            ? {
                  pattern: {
                      value: pattern.reg,
                      message: pattern.errorRegMsg,
                  },
              }
            : {}),
    }
    const showError = (errorsName?.message || !rule.ruleReg || !rule.len) && FieldState.isDirty

    return render ? (
        <InputItem
            className={`${label ? " lablebox " : " "} ${className}`}
            onClick={onClick}
        >
            {label && <TitleLabel>{label}</TitleLabel>}
            <Controller
                name={fieldName}
                control={control}
                render={(filed) => render({ ...filed, props })}
            />
        </InputItem>
    ) : (
        <InputItem
            className={`
                ${showError ? " error " : " "} 
                ${showClear ? " clearItem " : " "} 
                ${label ? " lablebox " : " "}
                ${values! ? " showClearIcon " : " "}
                ${showPlaceholder ? " placeholderBox " : ""}
                ${className}
           `}
        >
            {label && <TitleLabel>{label}</TitleLabel>}
            <BaseInputs
                style={style}
                onClick={onClick}
                id={"inputId-" + fieldName}
                type={inputType}
                maxLength={maxLength}
                {...register(fieldName, optionsReg)}
            />
            {showPlaceholder && (
                <InputLabel
                    className="inputTitle"
                    htmlFor={"inputId-" + fieldName}
                >
                    {placeholder}
                </InputLabel>
            )}
            {showClear && (
                <CleanInputBox onClick={Clear}>
                    <Svg
                        src={
                            showError
                                ? "login/clear_text_red.svg"
                                : "components/form_item/clear_text_icon.svg"
                        }
                    />
                </CleanInputBox>
            )}
            {errorsName && (
                <VerifyMessage>
                    <em>
                        <Svg src={"components/form_item/public_fail_icon.svg"} />
                    </em>
                    {errorsName?.message as string}
                </VerifyMessage>
            )}
        </InputItem>
    )
}

export default BaseFormItem

const InputItem = styled.div`
    position: relative;
    display: flex;
    &.lablebox {
        flex-direction: column;
        height: 81rem;
    }

    &.showClearIcon span {
        display: inline-block;
    }

    &.clearItem span.cleanIcon {
        right: 16rem;
    }

    &.showClearIcon .inputTitle {
        bottom: 26rem;
        font-size: 12rem;
        line-height: 16rem;
        color: #6a7081;
    }
    &.lablebox.showClearIcon .inputTitle {
        bottom: 26rem;
    }

    &.placeholderBox input {
        height: 56rem;
        padding-top: 24rem;
    }

    &.placeholderBox.showClearIcon span {
        bottom: 16rem;
    }

    &.error p {
        display: block;
    }

    &.error input {
        border-color: #fb2d60;
        background-color: #fee0e7;
    }

    &.error label.inputTitle {
        color: #fb2d60;
    }
`

const TitleLabel = styled.label`
    font-family: "Gilroy", sans-serif;
    font-weight: 500;
    font-size: 16rem;
    line-height: 24rem;
    letter-spacing: 0;
    color: #131416;
`

const BaseInputs = styled(BaseInput)`
    background-color: #f3f3f7;
    outline: none;
    border-radius: 8rem;
    border: 1rem solid #bbbdcc;
    height: 48rem;
    width: 100%;
    color: #3e4046;
    font-family: "Gilroy", sans-serif;
    padding-left: 16rem;

    &:focus {
        outline: none;
        border-color: #165dff;
    }

    &:focus + label {
        bottom: 32rem;
        font-size: 12rem;
        line-height: 16rem;
    }
`

const InputLabel = styled.label`
    position: absolute;
    bottom: 16rem;
    left: 16rem;
    font-family: "Gilroy", sans-serif;
    font-weight: 400;
    font-size: 16rem;
    line-height: 24rem;
    letter-spacing: 0;
    color: #9ca3b4;
    transition:
        bottom 0.18s linear,
        font-size 0.18s linear;
`

const CleanInputBox = styled.span`
    display: none;
    position: absolute;
    bottom: 12rem;
    right: 16rem;
    z-index: 10;
    width: 24rem;
    height: 24rem;

    &.cleanIcon {
        right: 45rem;
    }
`

const VerifyMessage = styled.p`
    display: none;
    position: absolute;
    bottom: -32rem;
    left: 0;
    font-family: "Gilroy", sans-serif;
    font-weight: 400;
    font-size: 12rem;
    line-height: 16rem;
    letter-spacing: 0;
    color: #fb2d60;
    padding-left: 20rem;

    & > em {
        position: absolute;
        display: block;
        width: 16rem;
        height: 16rem;
        top: 0;
        left: 0;
        line-height: normal;
        text-align: center;
    }

    &.stepNextvm {
        display: block;
        position: initial;
        margin: 0;
        padding: 0;
    }

    &.stepNextvm::before {
        display: none;
    }

    &.codemsg {
        position: relative;
        margin: 0;
        bottom: -4rem;
        left: 0;
    }

    &.codemsg.error {
        display: block;
    }
`
